package dao;

import java.util.ArrayList;
import java.util.List;

import javax.ejb.Stateless;
import javax.faces.context.FacesContext;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.TypedQuery;
import javax.servlet.http.HttpServletRequest;

import util.Conversion;
import util.TesterViewConversion;
import dto.CandidateDTO;
import dto.CandidateViewDto;
import entities.Candidate;
import entities.Employee;
import entities.Interview;

/**
 * Session Bean implementation class CandidateDAO
 */
@Stateless
public class CandidateDAO implements CandidateDAORemote {
	@PersistenceContext
	EntityManager em;

	//@EJB
	//Conversion conv;
	/**
	 * Default constructor.
	 */
	public CandidateDAO() {
		// TODO Auto-generated constructor stub
	}
	
	// returns the candidates of an employee, with id employeeid
	public List<CandidateViewDto> getCandidates(int employeeid) { 
				List<CandidateViewDto> cList = new ArrayList<CandidateViewDto>();
		Employee emp = new Employee(); // creates an Employee object and sets
										// its id to employeeid
		emp.setId(employeeid);
	
		TypedQuery<Candidate> query = em.createQuery(
				"SELECT DISTINCT i.candidate FROM Interview i where i.employee = :id ORDER BY i.candidate.firstName DESC",
				Candidate.class);
		query.setParameter("id", emp);
		List<Candidate> resultList = query.getResultList(); // retrieves the
															// result
		TesterViewConversion con = new TesterViewConversion();
		for (Candidate c : resultList) { // for each found candidate
			List<Interview> interviews= c.getInterviews();
			List<Interview> interv= new ArrayList<Interview>();
			for (Interview i: interviews)
				if (i.getEmployee().getId()==employeeid) interv.add(i);
			c.setInterviews(interv);
			CandidateViewDto cDTO = new CandidateViewDto();
			try {
				cDTO = con.fromCandidateViewDto(c); // the Candidate object is
														// converted to
														// CandidateViewDto
				cList.add(cDTO);
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

		}
		//System.out.println("Size of the list is:"+cList.size());
		return cList; // the result is returned
	}
	
	// returns the candidates with id candidateid
	@Override
	public List<CandidateViewDto> getCandidatesById(int candidateid) { 
		List<CandidateViewDto> cList = new ArrayList<CandidateViewDto>();
		Candidate can= new Candidate(); // creates an Candidate object and sets
										// its id to candidateid
		can.setId(candidateid);
		TypedQuery<Candidate> query = em.createQuery(
				"SELECT distinct i.candidate FROM Interview i where i.candidate = :id",
				Candidate.class);
		query.setParameter("id", can);
		List<Candidate> resultList = query.getResultList(); // retrieves the
															// result
		TesterViewConversion con = new TesterViewConversion();
		for (Candidate c : resultList) { // for each found candidate
			CandidateViewDto cDTO = new CandidateViewDto();
			try {
				cDTO = con.fromCandidateViewDto(c); // the Candidate object is
														// converted to
														// CandidateViewDto
				cList.add(cDTO);
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

		}
		return cList; // the result is returned
	}
	
	public CandidateDTO getCandidateByID(int candidateID) throws Exception
	{
		Conversion conv=new Conversion();
		TypedQuery<Candidate> query = em.createQuery(
				"SELECT c from Candidate c where c.id = :id",
				Candidate.class);
		query.setParameter("id",candidateID);
		List<Candidate> resultList = query.getResultList(); 
		if(resultList.size()>0)
			return conv.fromCandidateToCandidateDTO(resultList.get(0));
		return null;
	}
	
	/**
	 * Return all candidates
	 */
	public List<CandidateDTO> getAllCadidates() {
		

		TypedQuery<Candidate> query = em.createQuery("SELECT c FROM Candidate c", Candidate.class);
		List<CandidateDTO> lista = new ArrayList<CandidateDTO>();
		List<Candidate> result = query.getResultList();
		if(result.size()>0)
		for (Candidate c : result) {
			CandidateDTO candidates = new CandidateDTO();
			
			candidates.setId(c.getId());
			candidates.setFirstName(c.getFirstName());
			candidates.setLastName(c.getLastName());
			candidates.setEmail(c.getEmail());
			candidates.setLink(c.getLink());
			lista.add(candidates);
		}
		return lista;
	}

	@Override
	public List<CandidateDTO> getCandidatesForTester(int employeeid) {
		
		
		List<CandidateDTO> lista = new ArrayList<CandidateDTO>();
		Employee emp = new Employee(); // creates an Employee object and sets
										// its id to employeeid
		emp.setId(employeeid);
	
		TypedQuery<Candidate> query = em.createQuery(
				"SELECT DISTINCT i.candidate FROM Interview i where i.employee = :id",
				Candidate.class);
		query.setParameter("id", emp);
		List<Candidate> resultList = query.getResultList(); // retrieves the
															// result

		for (Candidate c : resultList) {
			CandidateDTO candidates = new CandidateDTO();
			
			candidates.setId(c.getId());
			candidates.setFirstName(c.getFirstName());
			candidates.setLastName(c.getLastName());
			candidates.setEmail(c.getEmail());
			candidates.setLink(c.getLink());
			lista.add(candidates);
		}
		return lista;
		}
	
	/**Generates a link for a candidate having candidateID as ID. If the candidate already has a link, the function returns null.*/
	public String generateLink(int candidateID) { 
		Candidate c;
		TypedQuery<Candidate> query = em.createQuery(
				"SELECT c from Candidate c where c.id = :id",
				Candidate.class);
		query.setParameter("id",candidateID);
		List<Candidate> resultList = query.getResultList(); 
		c = resultList.get(0);
		
		HttpServletRequest request = 
			(HttpServletRequest)FacesContext
				.getCurrentInstance()
					.getExternalContext()
						.getRequest();
		System.out.println("Request is: "+c.getLink());
		if (c.getLink() == "" || c.getLink()== null) {
			String encryptedEmail = "";
			for (int i = 0 ; i < c.getEmail().length() ; i++) {
				encryptedEmail = encryptedEmail + Integer.toHexString((int) c.getEmail().charAt(i));
			}
			String link;
			link = "http://" + request.getServerName() + ":" + request.getServerPort() + request.getContextPath() + "/faces/afterLink.xhtml?link=" + encryptedEmail;
			c.setLink(link);
			System.out.println("Link is returned as: "+link);
			em.merge(c);
			return link;
	}
		return null;
	}
	
	/** 
	 * Returns the a users link if he has one, returns null otherwise.
	 * */
	public String getLink(int candidateID) {
		TypedQuery<String> query = em.createQuery(
				"SELECT c.link from Candidate c where c.id = :id",
				String.class);
		query.setParameter("id",candidateID);
		String link = query.getSingleResult(); 
		if (link != null && link != "") {
			System.out.println("link is: "+link);
			return link;
		}
		return null;
	}
	
	/**Returns the candidate whose link contains the given linkParameter. If no such candidate is found, it returns null.*/
	public CandidateDTO getCandidateByLink(String linkParameter) {
		try {
			System.out.println(linkParameter);
			Candidate c;
			CandidateDTO cDTO;
			Conversion conv=new Conversion();
			TypedQuery<Candidate> query = em.createQuery(
					"SELECT c from Candidate c where c.link like :link",
					Candidate.class);
			query.setParameter("link","%" + linkParameter);
			List<Candidate> resultList = query.getResultList(); 
			if (resultList.size() > 0) {
				c = resultList.get(0);
				cDTO = conv.fromCandidateToCandidateDTO(c);
				return cDTO;
			}
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		return null;
	}
		
	@Override
	public void addCandidate(CandidateDTO cDTO)throws Exception{
		try {
			Conversion conv = new Conversion();

			Candidate emp = conv.fromCandidateDTOToCandidate(cDTO);
			
			em.persist(emp);
			
			TypedQuery<Candidate> query = em.createQuery(
					"SELECT c from Candidate c where c.email like :email",
					Candidate.class);
			query.setParameter("email",emp.getEmail());
			List<Candidate> resultList = query.getResultList(); 
			
			int id=resultList.get(0).getId();
			emp.setLink(generateLink(id));
			em.merge(emp);

		} catch (Exception e) {
			e.printStackTrace();
			try {
				throw new Exception("Error adding new candidate!", e);
			} catch (Exception e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
		}
	}
	
	@Override
	public void deleteCandidate(CandidateDTO cDTO) throws Exception{
		Candidate e=em.find(Candidate.class, cDTO.getId());
		if(e!=null){
			em.remove(e);
		}else{
			throw new Exception("Candidate could not been removed!");
		}
	}
	
	@Override
	public boolean CandidateHasInterviews(CandidateDTO cDTO){
		Candidate e=em.find(Candidate.class, cDTO.getId());
		if(e!=null){
			if(e.getInterviews().size()!=0)
				return true;
		}else{
			return false;
		}
		
		return false;
	}
	
}
